/*
 * Copyright (c) 2010 CCX(China) Co.,Ltd. All Rights Reserved.
 *
 * This software is the confidential and proprietary information of
 * CCX(China) Co.,Ltd. ("Confidential Information").
 * It may not be copied or reproduced in any manner without the express 
 * written permission of CCX(China) Co.,Ltd.
 *
 * Author: Wangyaoxi
 * Date: 2010-4-13 下午12:43:28
 */
package cn.com.ccxe.dao;

import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.ccxe.manage.db.CcxDB;

/**
 * 事务管理类<br>
 * 封转了需要事务管理的方法，并为其提供事务管理的功能， 要使用这项服务，只需将数据库实例交给{@link TransactionManager} 直接使用
 * {@link #start()}方法即可(再无需添加任何事务管理代码)。<br>
 * excute()方法是 对{@link CcxDB#executeUpdate(String sqlKey, Object[] sqlParameters)}
 * 的封装， 所以只支持插入、删除、修改操作。
 * 
 * @author hetao
 * 
 */
public class TransactionManager {

	private CcxDB db;
	private static final Logger logger = LoggerFactory.getLogger(TransactionManager.class);

	/**
	 * 传入数据库实例，为其添加事务管理功能。
	 * 
	 * @param db
	 */
	public TransactionManager(CcxDB db) {
		this.db = db;
	}

	/**
	 * 开始事务
	 */
	private void beginTransaction() {
		try {
			db.setAutoCommit(false);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * 进行事务管理
	 * 
	 * @param sql
	 * @param parametes
	 * @return
	 */
	public OperationStatus execute(String sql, Object[] parametes) {
		try {
			if (db == null) {
				throw new NullPointerException("获取数据库实例失败！");
			}
			beginTransaction();

			int result = db.executeUpdate(sql, parametes);

			if (result > 0) {
				commit();
				return OperationStatus.SUCCESS;
			}
			rollback();
			return OperationStatus.FAILURE;
		} catch (InsertException e) {
			rollback();
		} catch (Exception e) {
			rollback();
			logger.error("执行操作失败！{}\n{}", e.getMessage(),e.getStackTrace());
		}
		return OperationStatus.ERORR;
	}

	/**
	 * 执行多条SQL，但请注意SQL语句执行顺序！
	 * 
	 * @param statements
	 * @return
	 */
	public OperationStatus multipleExecute(Map<String, Object[]> statements) {
		statements.size();
		int result = 0;
		isEmptyDB(db);
		try {
			beginTransaction();
			for (Map.Entry<String, Object[]> statement : statements.entrySet()) {
				result += db.executeUpdate(statement.getKey(), statement.getValue());
			}
			if (result == statements.size()) {
				commit();
				return OperationStatus.SUCCESS;
			}
			rollback();
			return OperationStatus.FAILURE;
		} catch (Exception e) {
			rollback();
			logger.error("执行多个操作失败！", e);
			return OperationStatus.ERORR;
		}
	}

	/**
	 * 提交
	 * 
	 * @throws Exception
	 */
	private void commit() throws Exception {
		if (db == null) {
			throw new NullPointerException("数据库实例为空或没有获取，无法提交事务！");
		}
		db.commit();
	}

	/**
	 * 执行回滚操作
	 * 
	 * @param ccxDB
	 */
	private void rollback() {
		try {
			db.rollback();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	private void isEmptyDB(CcxDB db) {
		if (db == null) {
			throw new NullPointerException("获取数据库实例失败！");
		}
	}
}
